//
//  SearchingSortedListView.swift
//  DataStructure
//
//  Created by kys-20 on 2019/8/27.
//  Copyright © 2019 kys-20. All rights reserved.
//

import Foundation
import UIKit
class SearchingSortedListView: UIView {
    
    let labelTextArray = ["6","12","112","142","233","236","250","260","268","288","320","418","477","514","545","555","557","561","563","673","697","701","721","737","738","796","836","839","870","940","944","988"]
    
    let textField = UITextField()//输入框
    let LinearSearchButton = UIButton()//入列按钮
    let BinarySearchButton = UIButton()//出列按钮
    let slider = UISlider()//滑块 用来控制时间
    let labelWIDTH : CGFloat = (UIScreen.main.bounds.width - 30)/8
    let blueCircleLabel = UILabel()
    let greeCircleLabel = UILabel()
    let orangeCircleLabel = UILabel()
    
    var sumTime : Double = 1.00 // 总时间
    var listLabelArray = [UILabel]()//列表
    var listLabelMarkArray = [UILabel]()//下标
    var seachAndResuLabelArray = [UILabel]()//
    var indexLabelArray = [UILabel]()
    var index = 0
    var timer:Timer!
    var timeNum = 0
    var taggetLabelArray = [UILabel]()
    var low = 0
    var high = 31
    var mid = 0
    var lowAndMidAndHigh = [UILabel]()
    
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        
        setUpUI()
    }
    //   初始界面
    func setUpUI(){
        
        
        slider.frame = CGRect(x: 10, y: UIScreen.main.bounds.height-100, width: UIScreen.main.bounds.width-20, height: 30)
        slider.minimumValue = 0
        slider.maximumValue = 4
        slider.value = 2.00
        self.addSubview(slider)
        slider.isContinuous = false//滑块滑动停止后才触发ValueChanged事件
        slider.addTarget(self, action: #selector(ActionSliderValueChange), for: .valueChanged)
        
        textField.frame = CGRect(x: 20, y: 35, width: 70, height: 40)
        textField.borderStyle = .roundedRect
        textField.layer.borderColor = UIColor.red.cgColor
        textField.layer.borderWidth = 1
        self.addSubview(textField)
        LinearSearchButton.frame = CGRect(x: 100, y: 35, width: 100, height: 40)
        LinearSearchButton.setTitle("Linear Search", for: .normal)
        LinearSearchButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
        LinearSearchButton.setTitleColor(UIColor.black, for: .normal)
        LinearSearchButton.backgroundColor = UIColor.white
        LinearSearchButton.layer.borderWidth = 1
        self.addSubview(LinearSearchButton)
        LinearSearchButton.addTarget(self, action: #selector(actionLinearSearchButton), for: .touchUpInside)
        
        BinarySearchButton.frame = CGRect(x: 210, y: 35, width: 100, height: 40)
        BinarySearchButton.setTitle("Binary Search", for: .normal)
        BinarySearchButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
        BinarySearchButton.setTitleColor(UIColor.black, for: .normal)
        BinarySearchButton.backgroundColor = UIColor.white
        BinarySearchButton.layer.borderWidth = 1
        BinarySearchButton.addTarget(self, action: #selector(actionBinarySearchButton), for: .touchUpInside)
        self.addSubview(BinarySearchButton)
        
        for i in 0...3{
            let label = UILabel()
            label.frame = CGRect(x: UIScreen.main.bounds.width/2-2*(labelWIDTH+15)+CGFloat(i)*(labelWIDTH+15), y: 100, width: labelWIDTH+15, height: labelWIDTH+15)
            label.textAlignment = .center
            if i%2 != 0{
                label.layer.masksToBounds = true
                label.layer.borderWidth = 0.5
                label.layer.borderColor = UIColor.black.cgColor
            }
            if i == 0 {
                label.text = "Seach"
            }
            if i == 2{
                label.text = "Result"
            }
            self.addSubview(label)
            seachAndResuLabelArray.append(label)
        }
        for i in 0...1{
            let label = UILabel()
            label.frame = CGRect(x: UIScreen.main.bounds.width/2-2*(labelWIDTH+15)+CGFloat(i)*(labelWIDTH+15), y: 100+(labelWIDTH+30), width: labelWIDTH+15, height: labelWIDTH+15)
            label.textAlignment = .center
            if i%2 != 0{
                label.layer.masksToBounds = true
                label.layer.borderWidth = 0.5
                label.layer.borderColor = UIColor.black.cgColor
                label.text = "0"
            }else{
                label.text = "Index"
            }
            label.isHidden = true
            self.addSubview(label)
            indexLabelArray.append(label)
        }
        for i in 0...5{
            let label = UILabel()
            label.frame = CGRect(x: CGFloat(i)*(labelWIDTH+15), y: 100+(labelWIDTH+30), width:  labelWIDTH+15, height:  labelWIDTH+15)
            label.textAlignment = .center
            if i == 0 {
                label.text = "low"
            }else if i == 2{
                label.text = "mid"
            }else if i == 4{
                label.text = "high"
            }else{
                label.layer.masksToBounds = true
                label.layer.borderWidth = 0.5
                label.layer.borderColor = UIColor.red.cgColor
            }
            label.isHidden = true
            self.addSubview(label)
            lowAndMidAndHigh.append(label)
        }
        for j in 0...3{
            for i in 0...7{
                let label = UILabel()
                label.frame = CGRect(x: 15+CGFloat(i)*CGFloat(labelWIDTH), y: 260+CGFloat(j)*(CGFloat(labelWIDTH)*2), width: labelWIDTH, height: labelWIDTH)
                label.textAlignment = .center
                label.text = labelTextArray[j*8+i]
                label.layer.masksToBounds = true
                label.layer.borderWidth = 0.5
                label.layer.borderColor = UIColor.black.cgColor
                self.addSubview(label)
                listLabelArray.append(label)
            }
        }
        for j in 0...3{
            for i in 0...7{
                let label = UILabel()
                label.frame = CGRect(x: 15+CGFloat(i)*CGFloat(labelWIDTH), y: 260+CGFloat(labelWIDTH)+CGFloat(j)*(CGFloat(labelWIDTH)*2), width: labelWIDTH, height: labelWIDTH)
                label.textAlignment = .center
                label.textColor = UIColor.blue
                label.text = String(j*8+i)
                self.addSubview(label)
                listLabelMarkArray.append(label)
            }
        }
        blueCircleLabel.center = indexLabelArray[1].center
        blueCircleLabel.bounds.size = CGSize(width: labelWIDTH, height: labelWIDTH)
        blueCircleLabel.layer.masksToBounds = true
        blueCircleLabel.layer.borderWidth = 1
        blueCircleLabel.layer.borderColor = UIColor.blue.cgColor
        blueCircleLabel.layer.cornerRadius = labelWIDTH/2
        blueCircleLabel.isHidden = true
        self.addSubview(blueCircleLabel)
        
        greeCircleLabel.center = indexLabelArray[1].center
        greeCircleLabel.bounds.size = CGSize(width: labelWIDTH, height: labelWIDTH)
        greeCircleLabel.layer.masksToBounds = true
        greeCircleLabel.layer.borderWidth = 1
        greeCircleLabel.layer.borderColor = UIColor.green.cgColor
        greeCircleLabel.layer.cornerRadius = labelWIDTH/2
        greeCircleLabel.isHidden = true
        self.addSubview(greeCircleLabel)
        
        orangeCircleLabel.center = indexLabelArray[1].center
        orangeCircleLabel.bounds.size = CGSize(width: labelWIDTH, height: labelWIDTH)
        orangeCircleLabel.layer.masksToBounds = true
        orangeCircleLabel.layer.borderWidth = 1
        orangeCircleLabel.layer.borderColor = UIColor.orange.cgColor
        orangeCircleLabel.layer.cornerRadius = labelWIDTH/2
        orangeCircleLabel.isHidden = true
        self.addSubview(orangeCircleLabel)
    }
    //    线性查找----------------------------------------------------------
    @objc func actionLinearSearchButton(){
        seachAndResuLabelArray[3].text = ""
        seachAndResuLabelArray[1].text = ""
        if textField.text != ""{
            buttonEnabledNo()
            index = getIndexNum()
            indexLabelArray[0].isHidden = false
            indexLabelArray[1].isHidden = false
            for i in lowAndMidAndHigh{
                i.isHidden = true
            }
            seachAndResuLabelArray[1].text = textField.text
            print(index)
            timeLinearSearch()
            threeCircleIsHidden()
            blueCircleLabel.isHidden = false
        }
    }
    
    func timeLinearSearch(){
        let animate = Animate.baseAnimationWithKeyPath("position", fromValue:CGPoint(x: indexLabelArray[1].center.x,y: indexLabelArray[1].center.y) , toValue:CGPoint(x: listLabelMarkArray[0].center.x, y: listLabelMarkArray[0].center.y) , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
        animate.isRemovedOnCompletion = false
        blueCircleLabel.layer.add(animate, forKey: "position")
        let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
        indexLabelArray[1].layer.borderColor = UIColor.red.cgColor
        indexLabelArray[1] .layer.add(borderWAnimate, forKey: "borderWidth")
        timeNum = timeNum + 1
        timer = Timer.scheduledTimer(timeInterval: sumTime, target: self, selector: #selector(actionTimeLinearSearch), userInfo: nil, repeats: true)
    }
    
    @objc func actionTimeLinearSearch(){
        if timeNum%2 == 1 {
            let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
            seachAndResuLabelArray[1].layer.borderColor = UIColor.red.cgColor
            seachAndResuLabelArray[1].layer.add(borderWAnimate, forKey: "borderWidth")
            listLabelArray[timeNum/2].layer.borderColor = UIColor.red.cgColor
            listLabelArray[timeNum/2].layer.add(borderWAnimate, forKey: "borderWidth")
            indexLabelArray[1].layer.borderColor = UIColor.black.cgColor
            timeNum = timeNum + 1
            if timeNum > index * 2{
                timer.invalidate()
                timeNum = 0
                timer = Timer.scheduledTimer(timeInterval: sumTime, target: self, selector: #selector(actionResult), userInfo: nil, repeats: true)
            }
        }else{
            let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
            indexLabelArray[1].layer.borderColor = UIColor.red.cgColor
            indexLabelArray[1] .layer.add(borderWAnimate, forKey: "borderWidth")
            indexLabelArray[1].text = String(timeNum/2)
            let animate = Animate.baseAnimationWithKeyPath("position", fromValue:CGPoint(x: listLabelMarkArray[timeNum/2-1].center.x, y: listLabelMarkArray[timeNum/2-1].center.y) , toValue:CGPoint(x: listLabelMarkArray[timeNum/2].center.x, y: listLabelMarkArray[timeNum/2].center.y) , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
            animate.isRemovedOnCompletion = false
            blueCircleLabel.layer.add(animate, forKey: "position")
            
            seachAndResuLabelArray[1].layer.borderColor = UIColor.black.cgColor
            listLabelArray[(timeNum - 1)/2].layer.borderColor = UIColor.black.cgColor
            
            timeNum = timeNum + 1
        }
    }
    
    @objc func actionResult(){
        seachAndResuLabelArray[1].layer.borderColor = UIColor.black.cgColor
        listLabelArray[index].layer.borderColor = UIColor.black.cgColor
        if textField.text! == listLabelArray[index].text!{
            seachAndResuLabelArray[3].text = String(index)
        }else{
            if index != 31 {
                seachAndResuLabelArray[3].text = "-1"
            }else{
                if Int(textField.text!)! > Int(listLabelArray[index].text!)!{
                    let animate = Animate.baseAnimationWithKeyPath("position", fromValue:CGPoint(x: listLabelMarkArray[31].center.x, y: listLabelMarkArray[31].center.y) , toValue:CGPoint(x: listLabelMarkArray[24].center.x, y: listLabelMarkArray[24].center.y+labelWIDTH*2) , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
                    animate.isRemovedOnCompletion = false
                    blueCircleLabel.layer.add(animate, forKey: "position")
                }
            }
            
        }
        timer.invalidate()
        buttonEnabledYes()
    }
    
    //    计算得到 index-------------------------------
    func getIndexNum() -> Int {
        var index = 0
        let textNum = Int(textField.text!)
        var listNum = Int(listLabelArray[index].text!)
        while textNum! > listNum! && index < listLabelArray.count - 1 {
            index = index + 1
            listNum = Int(listLabelArray[index].text!)
        }
        return index
    }
    
    //    二分查找-----------------------------------------------------------
    @objc func actionBinarySearchButton(){
        // ======================此处有问题 第二次二分查找时 圆圈不能 归位 记得修改===============================
        blueCircleLabel.center = lowAndMidAndHigh[1].center
        greeCircleLabel.center = lowAndMidAndHigh[3].center
        orangeCircleLabel.center = lowAndMidAndHigh[5].center
        seachAndResuLabelArray[3].text = ""
        seachAndResuLabelArray[1].text = ""
        if textField.text != ""{
            buttonEnabledNo()
            seachAndResuLabelArray[1].text = textField.text
            for i in lowAndMidAndHigh{
                i.isHidden = false
            }
            for i in indexLabelArray {
                i.isHidden = true
            }
            
            threeCircleIsHiddenNo()
            
            let animateLow = Animate.baseAnimationWithKeyPath("position", fromValue:CGPoint(x: lowAndMidAndHigh[0].center.x, y: lowAndMidAndHigh[0].center.y) , toValue:CGPoint(x: listLabelMarkArray[0].center.x, y: listLabelMarkArray[0].center.y) , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
            animateLow.isRemovedOnCompletion = false
            blueCircleLabel.layer.add(animateLow, forKey: "position")
            let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
            lowAndMidAndHigh[1].layer.borderColor = UIColor.red.cgColor
            lowAndMidAndHigh[1] .layer.add(borderWAnimate, forKey: "borderWidth")
            lowAndMidAndHigh[1].text = listLabelMarkArray[0].text
            timeNum = timeNum + 1
            timer = Timer.scheduledTimer(timeInterval: sumTime, target: self, selector: #selector(binarySearchArithmetic), userInfo: nil, repeats: true)
        }
    }
    //    二分查询 当 timeNum 等于 1 或 2 时为准备 动画 从3开始  每 4 次为一个循环 2345/6789/
    @objc func binarySearchArithmetic(){
        if timeNum == 1{
            let animateHigh = Animate.baseAnimationWithKeyPath("position", fromValue:CGPoint(x: lowAndMidAndHigh[5].center.x, y: lowAndMidAndHigh[5].center.y) , toValue:CGPoint(x: listLabelMarkArray[31].center.x, y: listLabelMarkArray[31].center.y) , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
            animateHigh.isRemovedOnCompletion = false
            orangeCircleLabel.layer.add(animateHigh, forKey: "position")
            let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
            lowAndMidAndHigh[5].layer.borderColor = UIColor.red.cgColor
            lowAndMidAndHigh[5] .layer.add(borderWAnimate, forKey: "borderWidth")
            lowAndMidAndHigh[5].text = listLabelMarkArray[31].text
        }else{
            if low <= high{
                if Int(listLabelArray[(low + high)/2].text!)! == Int(textField.text!)! {
                    index = (low + high)/2
                    print(index)
                    greeCircleLabelMove()
                    timeNum = -1
                    seachAndResuLabelArray[3].text = listLabelArray[index].text
                }else if (timeNum-2)%4 == 0{
                    let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
                    lowAndMidAndHigh[1].layer.borderColor = UIColor.red.cgColor
                    lowAndMidAndHigh[1] .layer.add(borderWAnimate, forKey: "borderWidth")
                    lowAndMidAndHigh[5].layer.borderColor = UIColor.red.cgColor
                    lowAndMidAndHigh[5] .layer.add(borderWAnimate, forKey: "borderWidth")
                }else if (timeNum-2)%4 == 1 {
                    greeCircleLabelMove()
                }else if (timeNum - 2)%4 == 2{
                    let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
                    lowAndMidAndHigh[3].layer.borderColor = UIColor.red.cgColor
                    lowAndMidAndHigh[3] .layer.add(borderWAnimate, forKey: "borderWidth")
                    listLabelArray[mid].layer.borderColor = UIColor.red.cgColor
                    listLabelArray[mid].layer.add(borderWAnimate, forKey: "borderWidth")
                    
                }else if Int(listLabelArray[mid].text!)! < Int(textField.text!)!{
                    blueCircleLabelMove()
                }else{
                    orangeCircleLabelMove()
                }
            }else{
                seachAndResuLabelArray[3].text = "-1"
                timeNum = -1
            }
        }
        timeNum = timeNum + 1
        if timeNum == 0 {
            low = 0
            mid = 0
            high = 31
            timer.invalidate()
            buttonEnabledYes()
        }
        print(timeNum)
    }
    // 绿色圆圈移动。也就是mid圆圈的移动
    func greeCircleLabelMove(){
        if timeNum-3 == 0{
            let midP = CGPoint(x: lowAndMidAndHigh[3].center.x, y: lowAndMidAndHigh[3].center.y)
            mid = (low + high)/2
            let midpN = CGPoint(x: listLabelMarkArray[mid].center.x, y: listLabelMarkArray[mid].center.y)
            let animate = Animate.baseAnimationWithKeyPath("position", fromValue: midP , toValue: midpN , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
            animate.isRemovedOnCompletion = false
            greeCircleLabel.layer.add(animate, forKey: "position")
            
        }else{
            let midP = CGPoint(x: listLabelMarkArray[mid].center.x, y: listLabelMarkArray[mid].center.y)
            mid = (low + high)/2
            let midpN = CGPoint(x: listLabelMarkArray[mid].center.x, y: listLabelMarkArray[mid].center.y)
            let animate = Animate.baseAnimationWithKeyPath("position", fromValue: midP , toValue: midpN , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
            animate.isRemovedOnCompletion = false
            greeCircleLabel.layer.add(animate, forKey: "position")
        }
        let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
        lowAndMidAndHigh[1].layer.borderColor = UIColor.red.cgColor
        lowAndMidAndHigh[1] .layer.add(borderWAnimate, forKey: "borderWidth")
        
        lowAndMidAndHigh[5].layer.borderColor = UIColor.red.cgColor
        lowAndMidAndHigh[5] .layer.add(borderWAnimate, forKey: "borderWidth")
        
        lowAndMidAndHigh[3].layer.borderColor = UIColor.red.cgColor
        lowAndMidAndHigh[3] .layer.add(borderWAnimate, forKey: "borderWidth")
        lowAndMidAndHigh[3].text = String(mid)
        
    }
    //蓝圈移动 low圈移动
    func blueCircleLabelMove(){
        mid = (low + high)/2
        let lowP = CGPoint(x: listLabelMarkArray[low].center.x, y: listLabelMarkArray[low].center.y)
        low = mid + 1
        let lowPN = CGPoint(x: listLabelMarkArray[low].center.x, y: listLabelMarkArray[low].center.y)
        let animate = Animate.baseAnimationWithKeyPath("position", fromValue: lowP , toValue: lowPN , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
        animate.isRemovedOnCompletion = false
        blueCircleLabel.layer.add(animate, forKey: "position")
        let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
        lowAndMidAndHigh[1].layer.borderColor = UIColor.red.cgColor
        lowAndMidAndHigh[1] .layer.add(borderWAnimate, forKey: "borderWidth")
        for i in listLabelArray{
            i.layer.borderColor = UIColor.black.cgColor
        }
        lowAndMidAndHigh[1].text = String(low)
    }
    //    黄圈移动。high圈
    func orangeCircleLabelMove(){
        mid = (low + high)/2
        let highP = CGPoint(x: listLabelMarkArray[high].center.x, y: listLabelMarkArray[high].center.y)
        high = mid - 1
        let highPN = CGPoint(x: listLabelMarkArray[high].center.x, y: listLabelMarkArray[high].center.y)
        let animate = Animate.baseAnimationWithKeyPath("position", fromValue: highP , toValue: highPN , duration: sumTime, repeatCount: 0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
        animate.isRemovedOnCompletion = false
        orangeCircleLabel.layer.add(animate, forKey: "position")
        let borderWAnimate =  Animate.baseAnimationWithKeyPath("borderWidth", fromValue: 0, toValue: 5, duration: sumTime/2, repeatCount: 2, timingFunction: nil)
        lowAndMidAndHigh[5].layer.borderColor = UIColor.red.cgColor
        lowAndMidAndHigh[5] .layer.add(borderWAnimate, forKey: "borderWidth")
        for i in listLabelArray{
            i.layer.borderColor = UIColor.black.cgColor
        }
        lowAndMidAndHigh[5].text = String(high)
    }
    //    使三个圈隐藏
    func threeCircleIsHidden(){
        blueCircleLabel.isHidden = true
        orangeCircleLabel.isHidden = true
        greeCircleLabel.isHidden = true
    }
    //    使三个圈显示
    func threeCircleIsHiddenNo(){
        blueCircleLabel.isHidden = false
        orangeCircleLabel.isHidden = false
        greeCircleLabel.isHidden = false
    }
    //    按钮不可点击
    func buttonEnabledNo(){
        LinearSearchButton.isEnabled = false
        BinarySearchButton.isEnabled = false
        slider.isEnabled = false
    }
    //    按钮可点击
    func buttonEnabledYes(){
        LinearSearchButton.isEnabled = true
        BinarySearchButton.isEnabled = true
        slider.isEnabled = true
    }
    //控制每一步动画总时间---------------------------------------------------
    @objc func ActionSliderValueChange(){
        if Double(slider.value) <= 0.0001{
            sumTime = 0.0001
        }else{
            sumTime = Double(slider.value)
        }
        
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
